#!/usr/bin/python
# This file is part of ModularBot.
# Copyright (C) 2005 Pierre Ducroquet (pierre.linux59@wanadoo.fr)

# ModularBot is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# ModularBot is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with ModularBot; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


from IRCClient import IRCClient
import imp, IRC_conf, time, Context, sys
import floodmanager

class ModularBot(IRCClient):
	def __init__(self, config):
		self.config = config
		IRCClient.__init__(self, config.url, config.port, config.nick, config.ident, config.realname, config.bind)
		self.noticing = False
		self.nickname = config.nick
		for attr in ["versionNum", "versionName", "versionEnv"]:
			setattr(self, attr, getattr(config, attr))
		self.core_mod = imp.load_source("", "Core.py")
		self.core = self.core_mod.Core(self, self.config)
		self.versionString = "%s@%s - %s" % (self.versionName, self.versionEnv, self.versionNum)
		self.setFloodManager(floodmanager.FloodManager)

	def setFloodManager (self, floodManager):
		# Argument : floodManager **CLASS** and not **OBJECT**
		if hasattr(self, "floodmgr"):
			self.floodmgr.stop()
		self.floodmgr = floodManager((lambda channel, msg: IRCClient.say(self, channel, msg)), (lambda channel, msg: IRCClient.notice(self, channel, msg)))
		self.floodmgr.start()
	
	def privmsg(self, ctxte):
		if ctxte.message == "%s: CORE_RELOAD" % self.nickname:
			if self.core.rights.is_core_admin(ctxte.user) and self.core.rights.logged_in(ctxte.user):
				print "------CORE RELOAD------"
				del self.core
				self.core_mod = imp.load_source("", "Core.py")
				self.core = self.core_mod.Core(self, self.config)
				return
		self.core.answer(ctxte)
	
	def say (self, channel, message):
		try:
			msg = message.encode(self.config.charset)
			message = msg
		except:
			print "Encoding problem with %s" % message
		if len(message) > 450:
			broke = False
			part1 = ""
			part2 = ""
			try:
				for pos in range(350,len(message)):
					if message[pos] in [".", ",", ";", ":"] and message[pos+1] == " ":
						broke = True
						part1 = message[:pos+2]
						part2 = message[pos+2:]
						break
			except IndexError:
				pass
			if not broke or len(part1) > 450:
				for pos in range(350,len(message)):
					if message[pos] == " ":
						broke = True
						part1 = message[:pos]
						part2 = message[pos:]
						break
			if broke:
				self.floodmgr.send((channel, part1, self.noticing))
				self.say(channel, part2)
				return
		else:
			self.floodmgr.send((channel, message, self.noticing))
	
	def signedOn(self):
		print "joining ", config.channel
		self.join(config.channel)
	def joined(self, channel):
		for logon in config.logons:
			eval(logon)
		self.core.event("botjoinevent", (channel,))
	def userJoined(self, user, channel):
		user = user.split("!", 1)[0]
		self.core.event("joinevent", (user, channel))
	def userKicked(self, user, channel, kicker, reason):
		user = user.split("!", 1)[0]
		self.core.event("kickevent", (user, channel, kicker, reason))
	def userRenamed(self, oldname, newname):
		self.core.event("renameevent", (oldname, newname))
	def userLeft(self, user, channel):
		user = user.split("!", 1)[0]
		self.core.event("leftevent", (user, channel))
	def modeChanged (self, user, channel, set, modes, args):
		user = user.split("!", 1)[0]
		self.core.event("modeevent", (user, channel, set, modes, args))
	def numericAnswer(self, cmd_number, line):
		self.core.event("numanswer", (cmd_number, line))
	
	def PRIVMSG (self, line, line_splitted):
		channel = line_splitted[2]
		user = line_splitted[0][1:]
		msg = line[len(user) + len(channel) + len(line_splitted[1]) + 5:]
		if msg[0] == chr(1) and msg[-1] == chr(1):
			ctcp_cmd = msg[1:-1].split(" ", 1)[0]
			if hasattr(self, "CTCP_" + ctcp_cmd):
				getattr(self, "CTCP_" + ctcp_cmd)(user, msg)
			else:
				print "CTCP command %s not found" % ctcp_cmd
		else:
			ctxte = Context.Context(user, channel, self, msg)
			self.privmsg(ctxte)
	
	def NOTICE (self, line, line_splitted):
		print "Notice not handled currently (risk of infinite loop)"
		channel = line_splitted[2]
		user = line_splitted[0][1:]
		print (channel, user)
		return
		msg = line[len(user) + len(channel) + len(line_splitted[1]) + 5:]
		ctxte = Context.Context(user, channel, self, msg)
		ctxte.from_notice = True
		self.privmsg(ctxte)

if __name__ == "__main__":
	if len(sys.argv) > 1:
		config = IRC_conf.IRCConf(sys.argv[-1])
	else:
		config = IRC_conf.IRCConf("bot_conf.xml")
	client = ModularBot (config)
	client.connect()
	client.run()